package com.iwhalecloud.bss.kite.cucc.order.accept.constructor.inst;

import com.google.common.collect.Sets;
import com.iwhalecloud.bss.kite.common.constant.KeyConsts;
import com.iwhalecloud.bss.kite.common.constant.TableConsts;
import com.iwhalecloud.bss.kite.common.util.KiteBeanUtils;
import com.iwhalecloud.bss.kite.common.util.KiteStringUtils;
import com.iwhalecloud.bss.kite.common.util.SeqUtils;
import com.iwhalecloud.bss.kite.cucc.order.accept.constructor.DataConstructorFactory;
import com.iwhalecloud.bss.kite.cucc.order.loader.IInstLoader;
import com.iwhalecloud.bss.kite.cucc.order.loader.InstLoaderFactory;
import com.iwhalecloud.bss.kite.cucc.order.util.AcceptUtils;
import com.iwhalecloud.bss.kite.dataservice.cache.CommonRegionCache;
import com.iwhalecloud.bss.kite.dataservice.cache.ProductCache;
import com.iwhalecloud.bss.kite.dataservice.entity.CommonRegion;
import com.iwhalecloud.bss.kite.dataservice.entity.inst.OfferInst;
import com.iwhalecloud.bss.kite.dataservice.entity.inst.OfferInstAttr;
import com.iwhalecloud.bss.kite.dataservice.entity.inst.OfferObjInstRel;
import com.iwhalecloud.bss.kite.dataservice.entity.inst.ProdInst;
import com.iwhalecloud.bss.kite.dataservice.entity.spec.OfferDetail;
import com.iwhalecloud.bss.kite.dataservice.entity.spec.Product;
import com.iwhalecloud.bss.kite.manager.api.IQuerySceneInstService;
import com.iwhalecloud.bss.kite.manager.enums.ActionType;
import com.iwhalecloud.bss.kite.manager.enums.InstType;
import com.iwhalecloud.bss.kite.manager.enums.RelType;
import com.iwhalecloud.bss.kite.manager.inst.KiteInst;
import com.iwhalecloud.bss.kite.manager.inst.KiteProdInst;
import com.iwhalecloud.bss.kite.manager.inst.change.KiteInstChange;
import com.iwhalecloud.bss.kite.manager.util.ManagerUtils;
import com.iwhalecloud.bss.kite.order.client.dto.InstContainer;
import com.iwhalecloud.bss.kite.order.client.dto.OrderRequest;
import com.ztesoft.bss.base.staticdata.CoreDataOffer;
import com.ztesoft.bss.base.staticdata.CoreDataProdInst;
import com.ztesoft.bss.common.util.SpringUtil;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

/**
 * 接入产品实例构造器
 * @version 1.0
 */
@Component
public class ProdInstConstructor extends InstConstructor<KiteProdInst, ProdInst> {

    private Map<String, String> countyTypeMap;

    @Override
    public String getTableName() {
        return TableConsts.ProdInst.getTableName();
    }

    @Override
    public ProdInst build(OrderRequest orderRequest, String prodInstId, Map<String, Object> params) {
        if (Objects.isNull(orderRequest) || StringUtils.isBlank(prodInstId)) {
            return null;
        }

        IQuerySceneInstService querySceneInstService = SpringUtil.getBean(IQuerySceneInstService.class);
        KiteProdInst kiteProdInst = querySceneInstService.getProdInst(orderRequest.getCustId(), prodInstId);
        ProdInst prodInst = convert(orderRequest, kiteProdInst, params);
        InstContainer.ofRequest(orderRequest).addProdInst(prodInst);

        if (Objects.nonNull(prodInst)) {
            OfferInst offerInst = orderRequest.getInstContainer().getOfferInstMap().get(prodInst.getCompInstId());
            if (Objects.isNull(offerInst)) {
                offerInst = buildOfferInst(orderRequest, prodInst);
                InstContainer.ofRequest(orderRequest).addOfferInst(offerInst);
                if (AcceptUtils.isAddInst(offerInst)) {
                    // 补充基础销售品实例新增的变动信息
                    AcceptUtils.addInstChange(orderRequest, offerInst.getOfferInstId(), InstType.BASE_OFFER_INST,
                        ActionType.A, "", "", "");
                }
            }

            OfferObjInstRel offerObjInstRel = buildOfferObjInstRel(orderRequest, offerInst, prodInst);
            InstContainer.ofRequest(orderRequest).addOfferObjInstRel(offerObjInstRel);
            if (AcceptUtils.isAddInst(offerObjInstRel)) {
                // 补充基础销售品实例明细新关系新增的变动信息
                AcceptUtils.addRelChange(orderRequest, offerInst.getOfferInstId(), InstType.BASE_OFFER_INST,
                    prodInst.getProdInstId(), InstType.PROD_INST, RelType.OFFER_OBJ_REL_TYPE_1000, KiteInst.ACTION_TYPE,
                    "", ActionType.A.name());
            }
        }

        return prodInst;
    }

    @Override
    public ProdInst convert(OrderRequest orderRequest, KiteProdInst kiteProdInst, Map<String, Object> params) {
        if (!ObjectUtils.allNotNull(orderRequest, kiteProdInst)) {
            return null;
        }

        ProdInst prodInst = super.convert(orderRequest, kiteProdInst, params);
        if (AcceptUtils.isModifyInst(prodInst)) {
            String key = ManagerUtils.join(kiteProdInst.getInstType(), kiteProdInst.getProdInstId());
            List<KiteInstChange> instChanges = orderRequest.getInstChangeMap().getOrDefault(key, new ArrayList<>());
            for (KiteInstChange instChange : instChanges) {
                if (!(Objects.equals(ActionType.M, instChange.getActionType())
                    && StringUtils.equalsIgnoreCase("town_flag", instChange.getFieldName()))) {
                    continue;
                }

                // 计算城乡类型
                String oldCountyType = prodInst.getCountyType();
                String newCountyType = getCountyTypeByTownFlag(prodInst.getTownFlag());
                if (!KiteStringUtils.equals(oldCountyType, newCountyType)) {
                    prodInst.setCountyType(newCountyType);
                    // 补充countyType的变动信息
                    AcceptUtils.addInstChange(orderRequest, prodInst.getProdInstId(), kiteProdInst.getInstType(),
                        ActionType.M, "countyType", oldCountyType, newCountyType);
                }

                break;
            }
        }

        return prodInst;
    }

    @Override
    public ProdInst newInst(OrderRequest orderRequest, KiteProdInst kiteProdInst) {
        if (!ObjectUtils.allNotNull(orderRequest, kiteProdInst)) {
            return null;
        }

        Date now = new Date();
        Product product = ProductCache.get(kiteProdInst.getProdId());
        CommonRegion commonRegion = CommonRegionCache.get(orderRequest.getLanId());

        ProdInst prodInst = KiteBeanUtils.transform(kiteProdInst, ProdInst.class, KiteInst.ACTION_TYPE);
        prodInst.setOwnerCustId(orderRequest.getCustId());
        prodInst.setActionType(ActionType.A.name());
        if (StringUtils.isBlank(prodInst.getUseCustId())) {
            prodInst.setUseCustId(orderRequest.getCustId());
        }
        prodInst.setProdTypeCd(KeyConsts.PROD_TYPE_CD_01);
        prodInst.setCreateDate(now);
        prodInst.setStateCd(KeyConsts.STATE_ONWAY);
        prodInst.setCompInstId(kiteProdInst.getOfferInstId());
        prodInst.setStatusDate(now);
        prodInst.setCreateStaff(orderRequest.getStaffId());
        prodInst.setResidFlag(KeyConsts.DEFAULT_RESID_FLAG);
        prodInst.setSpareFld0(kiteProdInst.getProdInstId());
        prodInst.setOfferId(Optional.ofNullable(product).map(Product::getBaseOfferId).orElse(null));
        prodInst.setAccProdInstId(kiteProdInst.getProdInstId());
        prodInst.setProdUseType(CoreDataProdInst.PRI_C_0019_1000);
        prodInst.setStatusCd(CoreDataProdInst.PRI_0002_130000);
        prodInst.setCreateOrgId(orderRequest.getOrgId());
        prodInst.setUpdateStaff(orderRequest.getStaffId());
        prodInst.setUpdateDate(now);
        prodInst.setBusiModDate(now);
        prodInst.setLastOrderItemId("-1");
        prodInst.setState(KeyConsts.STATE_ONWAY);
        prodInst.setEffDate(now);
        prodInst.setExpDate(AcceptUtils.getDefaultExpDate());
        prodInst.setAreaCode(Optional.ofNullable(commonRegion).map(CommonRegion::getAreaCode).orElse(null));
        prodInst.setSegmentId(KeyConsts.DEFAULT_SEGMENT_ID);
        // 设置集团产品编码
        prodInst.setGrpProdNbr(Optional.ofNullable(product).map(Product::getGrpProdNbr).orElse("-1"));
        prodInst.setXmInstId(SeqUtils.getNext(TableConsts.ProdInstExt));
        prodInst.setEntityName(KeyConsts.DEFAULT_ENTITY_NAME);
        prodInst.setRegionId(orderRequest.getRegionId());
        setAttrs(prodInst, kiteProdInst.getAttrMap(),
            Sets.newHashSet(StringUtils.upperCase(TableConsts.ProdInst.getTableName()),
                StringUtils.upperCase(TableConsts.ProdInstExt.getTableName())));

        if (StringUtils.isBlank(prodInst.getCountyType())) {
            // 计算城乡类型
            prodInst.setCountyType(getCountyTypeByTownFlag(prodInst.getTownFlag()));
        }

        return prodInst;
    }

    /**
     * 构造基础销售品实例
     * @param orderRequest
     * @param prodInst
     * @return
     */
    public OfferInst buildOfferInst(OrderRequest orderRequest, ProdInst prodInst) {
        if (!ObjectUtils.allNotNull(orderRequest, prodInst)) {
            return null;
        }

        OfferInst offerInst = null;
        if (AcceptUtils.isAddInst(prodInst)) {
            Date now = new Date();
            offerInst = new OfferInst();
            offerInst.setOfferInstId(prodInst.getCompInstId());
            offerInst.setOwnerCustId(prodInst.getOwnerCustId());
            offerInst.setActionType(prodInst.getActionType());
            offerInst.setProdInstId(prodInst.getProdInstId());
            offerInst.setOfferId(prodInst.getOfferId());
            offerInst.setProdTypeCd(prodInst.getProdTypeCd());
            offerInst.setUseCustId(prodInst.getUseCustId());
            offerInst.setCreateDate(now);
            offerInst.setStateCd(KeyConsts.STATE_ONWAY);
            offerInst.setLanId(prodInst.getLanId());
            offerInst.setRegionId(prodInst.getRegionId());
            offerInst.setCompInstId(prodInst.getCompInstId());
            offerInst.setCreateStaff(prodInst.getCreateStaff());
            offerInst.setSpareFld0(prodInst.getCompInstId());
            offerInst.setCustId(prodInst.getOwnerCustId());
            offerInst.setStatusDate(now);
            offerInst.setCreateOrgId(prodInst.getCreateOrgId());
            offerInst.setUpdateStaff(prodInst.getUpdateStaff());
            offerInst.setUpdateDate(now);
            offerInst.setBusiModDate(now);
            offerInst.setLastOrderItemId("-1");
            offerInst.setOfferKind(CoreDataOffer.OFF_0005_10);
            offerInst.setOfferType(CoreDataOffer.OFF_0005_10);
            offerInst.setStatusCd(CoreDataOffer.OFF_0003_1200);
        }
        else {
            IInstLoader<OfferInst> instLoader = InstLoaderFactory.getInstLoader(TableConsts.OfferInst.getTableName());
            offerInst = instLoader.getInst(TableConsts.OfferInst.getTableName(), prodInst.getCompInstId(),
                prodInst.getOwnerCustId());
            if (Objects.nonNull(offerInst)) {
                offerInst.setNewOwnerCustId(prodInst.getNewOwnerCustId());
                if (Objects.equals(ActionType.A.name(), offerInst.getActionType())) {
                    offerInst.setNewActionType(prodInst.getNewActionType());
                }
                else {
                    AcceptUtils.setActionType(offerInst, AcceptUtils.getActionType(prodInst));
                }

                String offerInstId = offerInst.getOfferInstId();
                String custId = offerInst.getOwnerCustId();
                Map<String, OfferInstAttr> offerInstAttrMap = OfferInstConstructor.getOfferInstAttrMap(offerInstId,
                    custId);
                orderRequest.getInstContainer().getOfferInstAttrMap().put(offerInstId, offerInstAttrMap);
            }
        }

        return offerInst;
    }

    /**
     * 构造基础销售品实例明细
     * @param orderRequest
     * @param offerInst
     * @param prodInst
     * @return
     */
    public OfferObjInstRel buildOfferObjInstRel(OrderRequest orderRequest, OfferInst offerInst, ProdInst prodInst) {
        if (!ObjectUtils.allNotNull(orderRequest, offerInst, prodInst)) {
            return null;
        }

        OfferObjInstRel offerObjInstRel = null;
        OfferObjInstRelConstructor offerObjInstRelConstructor = DataConstructorFactory
            .getRelConstructor(RelType.OFFER_OBJ_REL_TYPE);
        if (AcceptUtils.isAddInst(prodInst)) {
            OfferDetail offerDetail = offerObjInstRelConstructor.getOfferDetail(offerInst.getOfferId(),
                Sets.newHashSet(CoreDataOffer.OFF_C_0044_100000), prodInst.getProdId());

            offerObjInstRel = new OfferObjInstRel();
            offerObjInstRel.setOwnerCustId(orderRequest.getCustId());
            offerObjInstRel.setProdCompRoleCd(Optional.ofNullable(offerDetail).map(OfferDetail::getRoleId).orElse("-1"));
            offerObjInstRel.setObjType(Optional.ofNullable(offerDetail).map(OfferDetail::getObjType).orElse("-1"));
            offerObjInstRel.setLanId(orderRequest.getLanId());
            offerObjInstRel.setInstanceId(prodInst.getProdInstId());
            offerObjInstRel.setCompInstId(offerInst.getOfferInstId());
            offerObjInstRel.setCreateStaff(orderRequest.getStaffId());
            offerObjInstRel.setDetailId(Optional.ofNullable(offerDetail).map(OfferDetail::getDetailId).orElse("-1"));
            offerObjInstRel.setMcompInstId(offerInst.getOfferInstId());
            offerObjInstRel.setOfferInstId(offerInst.getOfferInstId());
            offerObjInstRel.setObjId(prodInst.getProdInstId());
            offerObjInstRel.setRoleId(Optional.ofNullable(offerDetail).map(OfferDetail::getRoleId).orElse("-1"));

            offerObjInstRelConstructor.fillNewOfferObjInstRel(offerObjInstRel);
        }
        else {
            offerObjInstRel = offerObjInstRelConstructor.getInstRel(offerInst.getOfferInstId(),
                prodInst.getProdInstId(), CoreDataOffer.OFF_C_0044_100000, offerInst.getOwnerCustId());
            if (Objects.nonNull(offerObjInstRel)) {
                if (Objects.equals(ActionType.A.name(), offerObjInstRel.getActionType())) {
                    AcceptUtils.setActionType(offerObjInstRel, ActionType.K.name());
                }
                if (Objects.equals(ActionType.D.name(), prodInst.getActionType())) {
                    AcceptUtils.setActionType(offerObjInstRel, prodInst.getActionType());
                }
            }
        }

        return offerObjInstRel;
    }

    /**
     * 根据城乡标识获取城乡类型
     * @param townFlag
     * @return
     */
    private String getCountyTypeByTownFlag(String townFlag) {
        if (Objects.isNull(countyTypeMap)) {
            countyTypeMap = new HashMap<>();
            countyTypeMap.put(KeyConsts.TOWN_FLAG_1, KeyConsts.COUNTY_TYPE_20);
            countyTypeMap.put(KeyConsts.TOWN_FLAG_2, KeyConsts.COUNTY_TYPE_18);
            countyTypeMap.put(KeyConsts.TOWN_FLAG_3, KeyConsts.COUNTY_TYPE_15);
        }

        String countyType = countyTypeMap.get(townFlag);
        return Optional.ofNullable(countyType).orElse(KeyConsts.COUNTY_TYPE_30);
    }
}
